package com.tudou.libnavcompiler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.auto.service.AutoService;
import com.tudou.libnavannotation.ActivityDestination;
import com.tudou.libnavannotation.FragmentDestination;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
import javax.tools.FileObject;
import javax.tools.StandardLocation;


@AutoService(Processor.class)
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes({"com.tudou.libnavannotation.FragmentDestination",
        "com.tudou.libnavannotation.ActivityDestination"})
public class NavProcessor extends AbstractProcessor {

    private Messager messager;
    private Filer filer;
    private static final String OUTPUT_FILE_NAME = "destination.json";

    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        messager = processingEnv.getMessager();
        filer = processingEnv.getFiler();
    }

    FileOutputStream fos=null;
    OutputStreamWriter writer=null;
    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        Set<? extends Element> fragmentelements = roundEnvironment.getElementsAnnotatedWith(FragmentDestination.class);
        Set<? extends Element> activityelements = roundEnvironment.getElementsAnnotatedWith(ActivityDestination.class);

        if (!fragmentelements.isEmpty() || !activityelements.isEmpty()){
            HashMap<String, JSONObject> destMap =new HashMap<>();
            handleDestination(fragmentelements,FragmentDestination.class,destMap);
            handleDestination(activityelements,ActivityDestination.class,destMap);


            try {
                FileObject resource = filer.createResource(StandardLocation.CLASS_OUTPUT, "", OUTPUT_FILE_NAME);
                String resourcePath = resource.toUri().getPath();
                messager.printMessage(Diagnostic.Kind.NOTE,"resourcePath"+resourcePath);
                String appPath = resourcePath.substring(0, resourcePath.indexOf("app") + 4);
                String assetsPath=appPath+"src/main/assets";

                File file=new File(assetsPath);
                if (!file.exists()){
                    file.mkdirs();
                }

                File outPutFile=new File(file,OUTPUT_FILE_NAME);
                if (outPutFile.exists()){
                    outPutFile.delete();
                }
                outPutFile.createNewFile();
                String content = JSON.toJSONString(destMap);
                fos =new FileOutputStream(outPutFile);
                writer=new OutputStreamWriter(fos,"UTF-8");
                writer.write(content);
                writer.flush();

            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if (writer!=null){
                    try {
                        writer.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (fos!=null){
                    try {
                        fos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return true;
    }

    private void handleDestination(Set<? extends Element> elements, Class<? extends Annotation> annotationClass, HashMap<String, JSONObject> destMap) {
        for (Element element : elements) {
            TypeElement typeElement= (TypeElement) element;
            String pageUrl=null;
            int id=Math.abs(typeElement.hashCode());
            String clazName =typeElement.getQualifiedName().toString();
            boolean needLogin =false;
            boolean asStarter =false;
            boolean isFragmment =false;
            Annotation annotation=element.getAnnotation(annotationClass);
            if (annotation instanceof  FragmentDestination){
                FragmentDestination dest = (FragmentDestination) annotation;
                pageUrl=dest.pageUrl();
                asStarter=dest.asStarter();
                needLogin=dest.needLogin();
                isFragmment=true;
            }else if (annotation instanceof ActivityDestination){
                ActivityDestination dest = (ActivityDestination) annotation;
                pageUrl=dest.pageUrl();
                asStarter=dest.asStarter();
                needLogin=dest.needLogin();
                isFragmment=false;
            }

            if (destMap.containsKey(pageUrl)){
                messager.printMessage(Diagnostic.Kind.ERROR,"不同页面不允许使用同样的pageUrl"+clazName);
            }else {
                JSONObject jsonObject=new JSONObject();
                jsonObject.put("id",id);
                jsonObject.put("needLogin",needLogin);
                jsonObject.put("asStarter",asStarter);
                jsonObject.put("pageUrl",pageUrl);
                jsonObject.put("clazName",clazName);
                jsonObject.put("isFragmment",isFragmment);
                destMap.put(pageUrl, jsonObject);
            }
        }
    }
}
